package com.webwork.framework.config;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.webwork.framework.filter.ShiroLogoutFilter;
import com.webwork.framework.security.CustomRealm;

import net.sf.ehcache.CacheManager;

@Configuration
public class ShiroConfiguration {

	private String loginUrl = "/login";
	
	private String unauthorizedUrl = "/error";
	
	private String indexUrl = "/";
	
	@Value("${shiro.rememberMe.time}")
	private int rememberMeTime;
	
//	private Object captchaType;
//	private Object captchaEbabled;

	@Bean
	public EhCacheManager getEhCacheManager() {
		CacheManager cacheManager = CacheManager.getCacheManager("webwork");
		EhCacheManager em = new EhCacheManager();
		if (null == cacheManager) {
			em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
			return em;
		} else {
			em.setCacheManager(cacheManager);
			return em;
		}
	}

	@Bean
	public CustomRealm customRealm(EhCacheManager cacheManager) {
		CustomRealm realm = new CustomRealm();
		realm.setCacheManager(cacheManager);
		realm.setCredentialsMatcher(hashedCredentialsMatcher());
		return realm;
	}

	/**
     * 安全管理器
     */
    @Bean
    public SecurityManager securityManager(CustomRealm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(realm);
        // 记住我
        securityManager.setRememberMeManager(rememberMeManager());
        // 注入缓存管理器;
        securityManager.setCacheManager(getEhCacheManager());
        // session管理器
//        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }
    
    /**
     * cookie对象;
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //cookie生效时间30天,单位秒;
        simpleCookie.setMaxAge(rememberMeTime);
        return simpleCookie;
    }

    /**
     * cookie管理对象;记住我功能
     * @return
     */
    @Bean
	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(rememberMeCookie());
//		cookieRememberMeManager.setCipherKey用来设置加密的Key,参数类型byte[],字节数组长度要求16
//		cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
//		cookieRememberMeManager.setCipherKey("ZHANGXIAOHEI_CAT".getBytes())
        return cookieRememberMeManager;
	}
    
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		// 指定加密方式为MD5
		credentialsMatcher.setHashAlgorithmName("MD5");
		// 加密次数
		credentialsMatcher.setHashIterations(1024);
		credentialsMatcher.setStoredCredentialsHexEncoded(true);
		return credentialsMatcher;
	}
    
	/**
	 * 退出过滤器
	 */
	private ShiroLogoutFilter logoutFilter() {
		ShiroLogoutFilter logoutFilter = new ShiroLogoutFilter();
		logoutFilter.setRedirectUrl("/");
		return logoutFilter;
	}
    
    /**
     * 自定义验证码过滤器
     */
//    @Bean
//    public CaptchaValidateFilter captchaValidateFilter() {
//        CaptchaValidateFilter captchaValidateFilter = new CaptchaValidateFilter();
//        captchaValidateFilter.setCaptchaEbabled(captchaEbabled);
//        captchaValidateFilter.setCaptchaType(captchaType);
//        return captchaValidateFilter;
//    }
    
	/**
	 * Shiro 内置过滤器，可以实现权限相关的拦截器
	 *     anon:无需认证（登录）可以直接访问
	 *     authc:必须认证才能访问
	 *     user:如果使用rememberMe的功能才可以访问
	 *     perms:该资源得到资源权限才可以访问
	 *     role:该资源必须得到角色权限才可以访问
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// Shiro的核心安全接口,这个属性是必须的
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// 身份认证失败，则跳转到登录页面的配置
		shiroFilterFactoryBean.setLoginUrl(loginUrl);
		shiroFilterFactoryBean.setSuccessUrl(indexUrl);
		// 权限认证失败，则跳转到指定页面
		shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
		// Shiro连接约束配置，即过滤链的定义
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		// 对静态资源设置匿名访问
		filterChainDefinitionMap.put("/css/**", "anon");
		filterChainDefinitionMap.put("/img/**", "anon");
		filterChainDefinitionMap.put("/js/**", "anon");
		filterChainDefinitionMap.put("/layui/**", "anon");
		
		// 不需要拦截的访问
		filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/templates/**", "anon");

		filterChainDefinitionMap.put("/login", "anon");
		// 不需要拦截的访问
		filterChainDefinitionMap.put("/doLogin", "anon");
		// 退出 logout地址，shiro去清除session
		filterChainDefinitionMap.put("/logout", "logout");
		
//		filterChainDefinitionMap.put("/**", "authc");
		// 所有请求需要认证
		filterChainDefinitionMap.put("/**", "user");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

		// 系统权限列表
//		filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

		Map<String, Filter> filters = new LinkedHashMap<>();
//		filters.put("onlineSession", onlineSessionFilter());
//		filters.put("syncOnlineSession", syncOnlineSessionFilter());
//		filters.put("captchaValidate", captchaValidateFilter());
		// 注销成功，则跳转到指定页面
		filters.put("logout", logoutFilter());
		shiroFilterFactoryBean.setFilters(filters);

		return shiroFilterFactoryBean;
	}
	
	/**
     * Spring的一个bean , 由Advisor决定对哪些类的方法进行AOP代理 .
     * @return
     */
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		creator.setProxyTargetClass(true);
		return creator;
	}
	
	/**
	 * 开启Shiro注解通知器
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
			@Qualifier("securityManager") SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	@Bean
	public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}
	
}
